using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Common.Utilities.DLR;

namespace Workflows.Components
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="idx"></param>
    /// <param name="code"></param>
    public delegate void CodeSnippetUpdated(int idx, string code);

    /// <summary>
    /// 
    /// </summary>
    public partial class ConverterFactory : Form
    {
        private int _Idx;
        private Type _FromType;
        private Type _GlobalVarType;
        private string _CodeSnippet;
        public event CodeSnippetUpdated CodeSnippetUpdatedEvent;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idx"></param>
        /// <param name="fromType"></param>
        /// <param name="gVarType"></param>
        /// <param name="codeSnippet"></param>
        public ConverterFactory(int idx, Type fromType, Type gVarType, string codeSnippet)
        {
            this._Idx = idx;
            this._FromType = fromType;
            this._GlobalVarType = gVarType;
            this._CodeSnippet = codeSnippet;
            InitializeComponent();
        }

        private void ConverterFactory_Load(object sender, EventArgs e)
        {
            this.txt_FromTypeName.Text = this.GetTypeName(this._FromType);
            this.txt_ToTypeName.Text = this.GetTypeName(this._GlobalVarType);
            this.txt_MethodSignature.Text = string.Format("public {0} Convert(ref {0} gVarValue, {1} fromObj)",
                                                          this.GetTypeName(this._GlobalVarType),
                                                          this.GetTypeName(this._FromType));
            this.rt_Code.Text = this._CodeSnippet;
        }

        private void btn_Cancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btn_OK_Click(object sender, EventArgs e)
        {
            if (this.CodeSnippetUpdatedEvent != null)
                this.CodeSnippetUpdatedEvent(this._Idx, this.rt_Code.Text);

            this.Close();
        }

        private void btn_Test_Click(object sender, EventArgs e)
        {
            string codeSnippet = this.rt_Code.Text;
            string methodName = "Convert";
            MethodArgument arg0 = new MethodArgument("gVarValue", this._GlobalVarType, false);
            MethodArgument arg1 = new MethodArgument("fromObj", this._FromType, false);
            arg1.ArgValue = null;
            try
            {
                List<MethodArgument> args = new List<MethodArgument>();
                args.Add(arg0);
                args.Add(arg1);
                MethodConstructInfo methodBuilder = new MethodConstructInfo(this._GlobalVarType, methodName, args, codeSnippet);
                object result = CodeDomUtil.ExecuteMethod(methodBuilder);
                MessageBox.Show("Result: " + result.ToString());
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private string GetTypeName(Type type)
        {
            if (type.IsGenericType)
            {
                string genericTypeName = type.GetGenericTypeDefinition().Name;
                if (genericTypeName.IndexOf("`") > 0)
                {
                    genericTypeName = genericTypeName.Substring(0, genericTypeName.IndexOf("`"));
                }
                string paramName = string.Empty;
                Type[] paramTypes = type.GetGenericArguments();
                if (paramTypes != null && paramTypes.Length > 0)
                {
                    for (int i = 0; i < paramTypes.Length; i++)
                    {
                        paramName += paramTypes[i].Name;
                        if (i < paramTypes.Length - 1)
                            paramName += ",";
                    }
                }
                return genericTypeName + "<" + paramName + ">";
            }
            else
                return type.Name;
        }
    }
}